﻿using gt.webapi.core.Entity.Client;
using gt.webapi.core.Entity.Common;
using gt.webapi.core.Repositories;
using System;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;

namespace gt.webapi.core.Filters.Authority
{
    public class BasicAuthenticationFilter : AuthenticationFilterBase
    {
        public BasicAuthenticationFilter(IAuthorityRepository authorityRepository)
            : base(authorityRepository, false)
        {
        }

        public override async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            var simpleAuthority = AnalyzeSimpleAuthorityEntity(context);
            if (simpleAuthority == null) return;

            if (!m_authorityRepository.CheckAuthoritySecret(simpleAuthority.Appkey, simpleAuthority.Appsecret))
            {
                context.ErrorResult = new AuthenticationFailureResult(Constants.ERROR_INVALID_AUTH, context.Request);
                return;
            }

            ClaimsIdentity identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, simpleAuthority.Appkey) }, Constants.AUTHENTICATION_TYPE);
            context.Principal = new ClaimsPrincipal(identity);

            await Task.FromResult(0);
        }

        public override Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            var challenge = new AuthenticationHeaderValue(Constants.AUTH_BASIC_PARAM_Scheme);
            context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result);
            return Task.FromResult(0);
        }

        private SimpleAuthorityEntity AnalyzeSimpleAuthorityEntity(HttpAuthenticationContext context)
        {
            var authorization = context.Request.Headers.Authorization;
            if (authorization == null ||
                !string.Equals(authorization.Scheme, Constants.AUTH_BASIC_PARAM_Scheme, StringComparison.CurrentCultureIgnoreCase) ||
                string.IsNullOrEmpty(authorization.Parameter))
                return null;

            var data = Encoding.UTF8.GetString(Convert.FromBase64String(authorization.Parameter));
            if (string.IsNullOrEmpty(data)) return null;

            string[] array = data.Split(Constants.AUTH_BASIC_PARAM_SPLIT);
            if (array.Length != 2) return null;

            var appkey = array[0];
            var appsecret = array[1];
            if (string.IsNullOrEmpty(appkey) || string.IsNullOrEmpty(appsecret)) return null;

            return new SimpleAuthorityEntity { Appkey = appkey, Appsecret = appsecret };
        }
    }
}
